#include "TableSchema.h"
#include "util.h"
#include <rapidjson/document.h>

using namespace std;
using namespace rapidjson;

TableSchema::TableSchema() : TableSchema("", { }) { }

TableSchema::TableSchema(string name, initializer_list<tuple<string, size_t>> columnSchema) : Name(std::move(name)), ColumnSchemas(columnSchema)
{
    for(auto& i : ColumnSchemas)
    {
        if (get<1>(i) < 1)
            get<1>(i) = 1;
    }
}

string TableSchema::ToString() const
{
    auto dom = Document();
    dom.SetObject();
    dom.AddMember("name", Document().SetString(Name.c_str(), dom.GetAllocator()), dom.GetAllocator());
    auto columnSchema = Document();
    columnSchema.SetArray();
    for(auto & i : ColumnSchemas)
    {
        auto c = Document();
        c.SetObject();
        c.AddMember("name", Document().SetString(std::get<0>(i).c_str(), dom.GetAllocator()), dom.GetAllocator());
        c.AddMember("VERSIONS", Document().SetString(to_string(std::get<1>(i)).c_str(), dom.GetAllocator()), dom.GetAllocator());
        columnSchema.PushBack(c, dom.GetAllocator());
        auto buffer = rapidjson::StringBuffer();
        auto write = rapidjson::PrettyWriter<rapidjson::StringBuffer>(buffer);
    }
    dom.AddMember("ColumnSchema", columnSchema, dom.GetAllocator());
    return GetJsonString(dom);
}

bool TableSchema::FromString(const string& json)
{
    auto dom = Document();
    dom.Parse(json.c_str());
    if(dom.HasParseError())
        return false;
    if(!dom.HasMember("name"))
        return false;
    if(!dom.HasMember("ColumnSchema"))
        return false;
    if(!dom["name"].IsString())
        return false;
    if(!dom["ColumnSchema"].IsArray())
        return false;
    Name = dom["name"].GetString();
    ColumnSchemas.clear();
    auto tab = dom["ColumnSchema"].GetArray();
    for (auto i = tab.Begin(); i != tab.End(); i++)
    {
        if(!dom.HasMember("name"))
            return false;
        if(!dom.HasMember("VERSIONS"))
            return false;
        if(!dom["name"].IsString())
            return false;
        if(!dom["ColumnSchema"].IsString())
            return false;
        auto name = (*i)["name"].GetString();
        auto version = stol((*i)["VERSIONS"].GetString());
        ColumnSchemas.emplace_back(tuple(name, version));
    }
    return true;
}